//
//  IAPHelper.m
//  Hangman
//
//  Created by  Stefan Nestorov on 9/27/14.
//  Copyright (c) 2014 Ray Wenderlich. All rights reserved.
//

#import "IAPHelper.h"
#import "IAPProduct.h"
#import "Globals.h"
#import "Tracker.h"

@import StoreKit;


@interface IAPHelper () <SKProductsRequestDelegate, SKPaymentTransactionObserver>

@end


@implementation IAPHelper
{
    SKProductsRequest * _productsRequest;
    RequestProductsCompletionHandler _completionHandler;
    NSArray *_allAvailableProducts;
    IAPProduct *_energyProduct;
    NSArray *_storeProducts;
}


- (id)initWithProducts:(NSMutableDictionary *)products

{
    if ( (self = [super init]) ) {
        
        _products = products;
        [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
        
    }
    
    return self;
}

- (void)requestProductsWithCompletionHandler:(RequestProductsCompletionHandler)completionHandler
{
    // if the block that is passed in is on the stack, it won’t be available when you need it unless you copy it
    _completionHandler = [completionHandler copy];
    NSMutableSet *productIdentifiers = [NSMutableSet setWithCapacity:_products.count];
    
    for ( IAPProduct * product in _products.allValues ) {
        product.availableForPurchase = NO;
        [productIdentifiers addObject:product.productIdentifier];
    }
    
    _productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers];
    _productsRequest.delegate = self;
    [_productsRequest start];
    
}


#pragma mark - SKProductsRequestDelegate
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
    
    NSLog(@"Loaded list of products...");
    _productsRequest = nil;
    NSArray *skProducts = response.products;
    
    for ( SKProduct *skProduct in skProducts ) {
        IAPProduct *product = _products[skProduct.productIdentifier];
        product.skProduct = skProduct;
        product.availableForPurchase = YES;
    }
    
    // for debugging purposes
    for ( NSString *invalidProductIdentifier in response.invalidProductIdentifiers ) {
        IAPProduct *product = _products[invalidProductIdentifier];
        product.availableForPurchase = NO;
        NSLog(@"Invalid product identifier, removing: %@", invalidProductIdentifier);
    }
    
    NSMutableArray *availableProducts = [NSMutableArray array];
    for (IAPProduct *product in _products.allValues) {
        if ( product.availableForPurchase == YES ) {
            [availableProducts addObject:product];
            NSLog(@"availableProducts: %@",product.productIdentifier);
        }
    }
    
    _allAvailableProducts = [NSArray arrayWithArray:availableProducts];
    [self updateCustomProducts];
    
    if ( _completionHandler ) {
        _completionHandler(YES, availableProducts);
    } else {
        NSLog(@"_completionHandler = nil");
    }
    
    _completionHandler = nil;
    
}


- (void)request:(SKRequest *)request didFailWithError:(NSError *)error
{
    
    NSLog(@"Failed to load list of products: %@", error.localizedDescription);
    _productsRequest = nil;
    
    if ( _completionHandler ) {
        _completionHandler(FALSE, nil);
    } else {
        NSLog(@"_completionHandler is nil");
    }
    
    _completionHandler = nil;
    
}


- (void)buyProduct:(IAPProduct *)product
{
    
    NSAssert(product.allowedToPurchase, @"This product isn't allowed to be purchased!");
    
    NSLog(@"Buying %@...", product.productIdentifier);
    product.purchaseInProgress = YES;
    SKPayment * payment = [SKPayment paymentWithProduct:product.skProduct];
    [[SKPaymentQueue defaultQueue] addPayment:payment];
    
}


#pragma mark - SKPaymentTransactionObserver delegate method
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
    
    for ( SKPaymentTransaction * transaction in transactions ) {
        switch ( transaction.transactionState )
        {
            case SKPaymentTransactionStatePurchased:
                [self completeTransaction:transaction];
                [[NSNotificationCenter defaultCenter] postNotificationName:@"transaction complete" object:nil];
                break;
                
            case SKPaymentTransactionStateFailed:
                [self failedTransaction:transaction];
                [[NSNotificationCenter defaultCenter] postNotificationName:@"transaction complete" object:nil];
                break;
                
            case SKPaymentTransactionStateRestored:
                [self restoreTransaction:transaction];
                [[NSNotificationCenter defaultCenter] postNotificationName:@"transaction complete" object:nil];
            default:
                break;
        }
        
    };
    
}


- (void)completeTransaction:(SKPaymentTransaction *)transaction
{
    
    NSLog(@"completeTransaction...");
    [self provideContentForTransaction:transaction
                     productIdentifier:transaction.payment.productIdentifier];
    
}


- (void)restoreTransaction:(SKPaymentTransaction *)transaction
{
    
    [Tracker trackEvent:@"Restore Purchases" withParams:@{
                                                          @"Identifier" : transaction.originalTransaction.payment.productIdentifier,
                                                          }];
    
    NSLog(@"restoreTransaction...");
    [self provideContentForTransaction:transaction
                     productIdentifier:transaction.originalTransaction.payment.productIdentifier];
    
}


- (void)failedTransaction:(SKPaymentTransaction *)transaction
{
    
    NSLog(@"failedTransaction...");
    if ( transaction.error.code != SKErrorPaymentCancelled ) {
        NSLog(@"Transaction error: %@",transaction.error.localizedDescription);
    }
    
    IAPProduct *product = _products[transaction.payment.productIdentifier];
    [self notifyStatusForProductIdentifier: transaction.payment.productIdentifier string:@"Purchase failed."];
    product.purchaseInProgress = NO;
    [[SKPaymentQueue defaultQueue] finishTransaction: transaction];
    
}


- (void)notifyStatusForProductIdentifier:(NSString *)productIdentifier string:(NSString *)string
{
    
    IAPProduct * product = _products[productIdentifier];
    [self notifyStatusForProduct:product string:string];
    
}


- (void)notifyStatusForProduct:(IAPProduct *)product string:(NSString *)string
{
    // IMPLEMENTED IN SUBCLASS
}


- (void)provideContentForTransaction:(SKPaymentTransaction *)transaction
                   productIdentifier:(NSString *)productIdentifier
{
    
    [self provideContentForProductIdentifier:productIdentifier notify:YES];
    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
    
}


- (void)provideContentForProductIdentifier:(NSString *)productIdentifier notify:(BOOL)notify
{
    
    IAPProduct * product = _products[productIdentifier];
    [self provideContentForProductIdentifier:productIdentifier];
    
    if ( notify == YES ) {
        [self notifyStatusForProductIdentifier:productIdentifier string:@"Purchase complete!"];
    }
    product.purchaseInProgress = NO;
    
}


- (void)provideContentForProductIdentifier:(NSString *)productIdentifier
{
    // IMPLEMENTED IN SUBCLASS
}


#pragma mark - Restore Purchesses
- (void)restoreCompletedTransactions
{
    
    [[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
    
}


#pragma mark - Custom methods

- (void)updateCustomProducts
{
    
    for (IAPProduct *product in _allAvailableProducts) {
        
        // Set isEnergyPurchase = NO by Default
        product.isEnergyPurchase = NO;
        
        if ( [product.productIdentifier isEqualToString:OFFER_1]  ) {
            
            product.isEnergyPurchase = YES;
            _energyProduct = product;
            
            break;
            
        }
        
    }
    
    NSMutableArray *arrayWithoutEnergyProduct = [NSMutableArray arrayWithArray:_allAvailableProducts];
    [arrayWithoutEnergyProduct removeObject:_energyProduct];
    
    _storeProducts = [self bubbleSort:arrayWithoutEnergyProduct];
    
}


- (IAPProduct *)getEnergyProduct
{
    
    return _energyProduct;
    
}


- (NSArray *)getStoreProducts
{
    
    return _storeProducts;
    
}


#pragma mark - Helpers

-(NSArray *)bubbleSort:(NSMutableArray *)unsortedProductsArray
{
    
    long count = unsortedProductsArray.count;
    int i;
    BOOL swapped = YES;
    
    while ( swapped ) {
        
        swapped = NO;
        
        for ( i = 1; i < count; i++) {
            
            IAPProduct *currentProduct = unsortedProductsArray[i];
            NSString *currentProductLastChar = [currentProduct.productIdentifier substringFromIndex:[currentProduct.productIdentifier length] - 1];
            NSInteger currentProductNumber = [currentProductLastChar integerValue];
            
            IAPProduct *previousProduct = unsortedProductsArray[i-1];
            NSString *previousProductLastChar = [previousProduct.productIdentifier substringFromIndex:[previousProduct.productIdentifier length] - 1];
            NSInteger previousProductNumber = [previousProductLastChar integerValue];
            
            if ( previousProductNumber > currentProductNumber ) {
                
                [unsortedProductsArray exchangeObjectAtIndex:(i-1) withObjectAtIndex:i];
                swapped = YES;
                
            }
            
        }
        
    }
    
    return unsortedProductsArray;
    
}


@end

